/*
 * SimpleHTTPClient.java
 *
 * Created on 8 październik 2007, 20:56
 *
 */

package kosciak.blip4j.utils.http;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import kosciak.blip4j.utils.base64.Base64StringEncoder;
import org.apache.commons.codec.EncoderException;

/**
 * <CODE>SimpleHTTPClient</CODE> is simple HTTP client used by Blip4j
 * 
 * @author Wojtek 'KosciaK' Pietrzok
 * @since 0.1
 */
public class SimpleHTTPClient implements HTTPClient {
    
    private String host;
    private int port;
    private String file;
    private String protocol;
    
    private List<Header> headers = new ArrayList<Header>();
    private String content = "";
    
    /**
     * Creates a new instance of SimpleHTTPClient.
     * Default protocol is HTTP, port is 80
     * 
     * @param host a host that will listen for requests
     */
    public SimpleHTTPClient(String host) {
        this("http", host, 80);
    }
    
    /**
     * Creates a new instance of SimpleHTTPClient.
     * Default protocol is HTTP
     * 
     * @param host a host that will listen for requests
     * @param port a port
     */
    public SimpleHTTPClient(String host, int port) {
        this("http", host, port);
    }
    
    /**
     * Creates a new instance of SimpleHTTPClient.
     * Default port is 80.
     * 
     * @param protocol a protocol
     * @param host a host that will listen for requests
     */
    public SimpleHTTPClient(String protocol, String host) {
        this(protocol, host, 80);
    }
    
    /**
     * Creates a new instance of SimpleHTTPClient.
     * 
     * @param protocol a protocol
     * @param host a host that will listen for requests
     * @param port a port
     */
    public SimpleHTTPClient(String protocol, String host, int port) {
        this.protocol = protocol;
        this.host = host;
        this.port = port;
    }

    /**
     * Performs GET request
     * @param file a file to request
     * @return a HTTP response
     * @throws java.io.IOException if an error occurs
     */
    public HTTPResponse doGET(String file) throws IOException {
        return doMethod(file, "GET");
    }
    
    /**
     * Performs POST request
     * @param file a file to request
     * @param content a content of a request
     * @return a HTTP response
     * @throws java.io.IOException if an error occurs
     */
    public HTTPResponse doPOST(String file, String content) throws IOException {
        HttpURLConnection connection = doMethod(file, "POST").getConnection();
        setRequestContent(content);
        attachStringContent(connection);
        
        return new HTTPResponse(connection);
    }

    /**
     * Sets Basic authentication
     * @param username an username
     * @param password a password
     * @throws org.apache.commons.codec.EncoderException if an error occurs while Encoding username and password with Base64
     */
    public void setBasicAuthentication(String username, String password) throws EncoderException {
        Base64StringEncoder encoder = new Base64StringEncoder();
        String login = username + ":" + password;
        String encoded_login = encoder.encode(login);
        addRequestHeader(new Header("Authorization", "Basic " + encoded_login));
    }
    
    /**
     * Adds request header
     * @param key a name of header
     * @param value a value of a header
     */
    public void addRequestHeader(String key, String value) {
        addRequestHeader(new Header(key, value));
    }
    
    /**
     * Adds request header
     * @param header a request header
     */
    public void addRequestHeader(Header header) {
        headers.add(header);
    }
    
    /**
     * Adds a List of request headers
     * @param headers a List of request headers
     */
    public void addRequestHeaders(List<Header> headers) {
        headers.addAll(headers);
    }
/*    
    public void setRequestContent(byte[] bytes) {
        
    }
*/    
    private void setRequestContent(String content) {
        this.content = content;
    }
            
    private void setRequestContent(String key, String value) {
        setRequestContent(key + "=" + value);
    }
    
    private HTTPResponse doMethod(String file, String method) throws IOException {
        URL url = new URL(protocol, host, port, file);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        try {
            connection.setRequestMethod(method);
        } catch (ProtocolException ex) {
            ex.printStackTrace();
        }
        
        setHeaders(connection);
        
        connection.setDoOutput(true);
        
        return new HTTPResponse(connection);
        
    }
    
    private void setHeaders(URLConnection connection) {
        for (Header header : headers) {
            connection.addRequestProperty(header.getKey(), header.getValue());
        }       
    }
    
    private void attachStringContent(URLConnection connection) throws IOException{
        OutputStream os = connection.getOutputStream();
        os.write(content.getBytes());
        os.flush();
        os.close();
    }
}
